Skip to content

feat: Add StableApi marker and API diff check#2168

Merged
zeitlinger merged 2 commits into
mainfrom
api-diff-baseline-japicmp
Jun 2, 2026
Merged

feat: Add StableApi marker and API diff check#2168
zeitlinger merged 2 commits into
mainfrom
api-diff-baseline-japicmp

Conversation

@zeitlinger
Copy link
Copy Markdown
Member

@zeitlinger zeitlinger commented Jun 1, 2026

Summary

  • add @StableApi as the opt-in marker for published Java API
  • seed the guessed stable API surface from docs plus Micrometer/JMX usage
  • add mise run api-diff using japicmp against the configured baseline
  • add an API diff workflow that fails on incompatible published API changes

Notes

This is the bootstrap PR for the annotation-based API surface. Since 1.5.1 does not contain
@StableApi, the first diff is noisy and mostly shows the seeded API surface as new. After a
release contains the annotations, future diffs should be normal compatibility diffs.

The workflow does not post PR comments or upload artifacts. If the check fails, run this locally:

mise run api-diff

Reports are written to **/target/japicmp/*.

Intentional incompatible changes can be accepted by adding the PR label
breaking-api-change-accepted.

Validation

  • mise run api-diff
  • mise run build
  • mise run lint

@zeitlinger zeitlinger changed the title Add StableApi marker and API diff check feat: Add StableApi marker and API diff check Jun 1, 2026
@zeitlinger zeitlinger force-pushed the api-diff-baseline-japicmp branch 2 times, most recently from cbd01a5 to e296cbd Compare June 1, 2026 16:56
@zeitlinger zeitlinger added the breaking-api-change-accepted Accept breaking API changes label Jun 1, 2026
@zeitlinger zeitlinger force-pushed the api-diff-baseline-japicmp branch from e296cbd to 974e23a Compare June 1, 2026 17:09
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger zeitlinger force-pushed the api-diff-baseline-japicmp branch from 974e23a to 3431634 Compare June 1, 2026 17:15
baseline_version:
description: Version to compare the PR artifacts against
required: false
default: "1.5.1"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how should we keep this up to date? should we create an issue to add a post-release step automation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created #2170

Comment thread docs/stable-api-rationale.md Outdated
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger zeitlinger merged commit 768fd3a into main Jun 2, 2026
18 checks passed
@zeitlinger zeitlinger deleted the api-diff-baseline-japicmp branch June 2, 2026 09:46
zeitlinger added a commit that referenced this pull request Jun 2, 2026
…idiffs (#2174)

## Summary

Fixes the manual-bump drift in the api-diff baseline (#2170) and makes
API changes visible in review.

- **Single source of truth.** The baseline lives only in the
`<api.diff.baseline.version>` pom property (bumped from the
already-drifted `1.5.1` to the actual latest release `1.6.1`).
`mise.toml` and `api-diff.yml` no longer hardcode it.
- **Renovate owns the bump.** A custom regex manager tracks the latest
*published* `io.prometheus:prometheus-metrics-core` on Maven Central and
bumps the property on the `renovate/api-diff-baseline` branch. Because
Renovate only proposes published versions, there is no Maven Central
propagation race and no post-release workflow or app token needed.
- **Diffs committed to `docs/apidiffs/`.** `mise run api-diff` syncs the
japicmp per-module reports into `docs/apidiffs/<module>.diff` via
`.github/scripts/sync-api-diffs.sh`, stripping the volatile preamble so
files only churn on real API changes. The api-diff workflow fails if
they are stale, so every API change shows up in the PR diff.
- **Regeneration on bump.** `generate-api-diff-baseline.yml` regenerates
`docs/apidiffs` on the Renovate branch and pushes it back, mirroring
`generate-protobuf.yml`.
- `docs/apidiffs/**` is marked `linguist-generated` so flint skips it.

## Notes

- The seed diffs are large because `1.6.1` predates `@StableApi` (the
bootstrap noise documented in #2168). They shrink to near-empty once a
release contains the annotations.
- Like the protobuf flow, a `GITHUB_TOKEN` push doesn't re-trigger CI —
close/reopen the Renovate bump PR to run the api-diff check after
regeneration (noted in the workflow).

## Validation

- `mise run api-diff` (generates the 25 seed diffs; verified idempotent)
- `mise run lint`
- `renovate-config-validator --strict`, actionlint, zizmor

Closes #2170

## Also fixes a pre-existing compat-test break on `main`

`micrometer-compatibility` and `jmx-exporter-compatibility` fail on
`main` (e.g.
[#2173](#2173)), unrelated
to this change. The compat harness installs local artifacts with
`-Dmaven.test.skip=true`, which skips building the `*:test-jar`
artifacts that the `activeByDefault` `default` profiles declare as test
dependencies, breaking resolution (e.g.
`prometheus-metrics-exposition-textformats:jar:tests`).

Fixed by deactivating those profiles in the compat install (`-P
!default`), matching what the release task already does (`-P
release,!default`). Verified locally: full `mvnw install
-Dmaven.test.skip=true -P !default` → BUILD SUCCESS.

## Reviewer note: the seed diffs show the full stable surface (expected)

The committed `docs/apidiffs/current_vs_latest/*.txt` list the
**entire** `@StableApi` surface as additions, not a small delta. This is
the documented bootstrap state from #2168, not a bug:

- The japicmp include filter is
`@io.prometheus.metrics.annotations.StableApi`. The baseline `1.6.1` jar
predates `@StableApi`, so its filtered surface is empty → every
annotated class in current code registers as "NEW". The header genuinely
compares against the `1.6.1` jar; the annotation filter is what makes
everything look added.
- Verified the filter is correct: only `@StableApi`-annotated types
appear (non-stable classes like `CKMSQuantiles`/`Buffer` are excluded;
`CallbackMetric` shows only as an inherited `NEW SUPERCLASS` reference).
It is the same root cause as the `breaking-api-change-accepted` label on
this PR.

It self-corrects after the next release ships `@StableApi`: Renovate
bumps the baseline to that release, the bump workflow regenerates
`current_vs_latest/` as an annotated-vs-annotated (near-empty) diff, and
the archived `<new>_vs_<old>/` becomes the first real release diff. So
the current files are best read as a one-time record of the initial
declared stable API surface.

---------

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-api-change-accepted Accept breaking API changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants